/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2010>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Text;
using MyPhotoIndex.Plugins.Share.Facebook.Properties;
using System.Drawing;
using System.Collections.ObjectModel;
using System.Threading;
using System.IO;
using System.Drawing.Imaging;
using MyPhotoIndex.Utilities;
using System.Windows.Forms;
using MyPhotoIndex.Plugins.Share.Facebook.Fb_API;
using MyPhotoIndex.Interfaces.Plugins;
using MyPhotoIndex.Interfaces;
using MyPhotoIndex.Interfaces.Imaging;
using MyPhotoIndex.Interfaces.ImageFormatProviders;
using MyPhotoIndex.Interfaces.Tagging;

namespace MyPhotoIndex.Plugins.Share.Facebook
{
    public class FacebookPlugin : ISharePlugin
    {
        private IApplicationContext m_applicationContext;
        private System.Drawing.Size m_imageSize;
        private int m_progressValue;
        private Semaphore m_semaphore = new Semaphore(1, 1);

        private Authentication m_auth;


        #region ISharePlugin Members

        public System.Drawing.Image Icon
        {
            get { return Resources.fbIcon; }
        }

        public void Send(ReadOnlyCollection<IImageData> imageFiles, Size imageSize)
        {
            m_imageSize = imageSize;

            m_applicationContext.ProcessProgress.IsInfinite = true;
            m_applicationContext.ProcessProgress.ProcessDescription = this.ToString();
            m_applicationContext.ProcessProgress.Running = true;

            if (m_auth == null)
            {
                m_auth = new Authentication();
                bool ok = m_auth.SignIn("650b150054e483ccb33c51844fdeb4ac", "c524b77e3f9ee049580fbdf6efec0ee9");
                if (ok == false)
                {
                    m_auth = null;
                    m_applicationContext.ProcessProgress.Running = false;
                    return;
                }
            }

            m_applicationContext.ProcessProgress.Running = false;

            ThreadPool.QueueUserWorkItem(new WaitCallback(SendAsync), imageFiles);
        }

        private Dictionary<string, string> PrepareFilesForUpload(ReadOnlyCollection<IImageData> imageFiles)
        {
            Dictionary<string, string> files = new Dictionary<string, string>();
            foreach (IImageData imageData in imageFiles)
            {
                string tempFile = Path.GetRandomFileName();
                tempFile = Path.ChangeExtension(tempFile, "Jpg");
                tempFile = Path.Combine(Path.GetTempPath(), tempFile);

                using (Image image = imageData.FormatProvider.LoadImage(imageData, m_imageSize))
                {
                    if (image != null)
                    {
                        IImageFormatProvider jpgProvider = ImageFormatProviders.ImageFormatProviders.Default["jpg"];
                        jpgProvider.SaveImage(image, imageData, tempFile);

                        files.Add(imageData.FileName, tempFile);
                    }
                    else
                    {
                        Logger.Log(String.Format("Image was not found {0}", imageData.ToString()));
                    }
                }
            }

            return files;
        }

        public void SendAsync(Object state)
        {
            m_applicationContext.ProcessProgress.IsInfinite = true;
            m_applicationContext.ProcessProgress.ProcessDescription = this.ToString();
            m_applicationContext.ProcessProgress.Running = true;

            ReadOnlyCollection<IImageData> imageFiles = state as ReadOnlyCollection<IImageData>;

            ImageUploader uploader = new ImageUploader(m_auth);
            uploader.ImageUploadEvent += new EventHandler<ProgressEventArgs>(uploader_ImageUploadEvent);

            Dictionary<string, string> files = PrepareFilesForUpload(imageFiles);

            int totalSize = 0;
            foreach (string file in files.Values)
            {
                FileInfo fi = new FileInfo(file);
                totalSize += (int)fi.Length;
            }

            List<String> tagList = buildTagList(imageFiles);

            PhotoAlbums photoAlbum = new PhotoAlbums(m_auth);
            SelectAlbumForm saf = new SelectAlbumForm(photoAlbum, FacebookPluginSettings.Default.LastUsedAlbumId, tagList, imageFiles.Count);
            saf.StartPosition = FormStartPosition.CenterScreen;
            saf.TopMost = true;
            DialogResult res = saf.ShowDialog();
            if (res != DialogResult.OK)
            {
                m_applicationContext.ProcessProgress.Running = false;
                return;
            }

            String albumId = saf.AlbumId;
            if (String.IsNullOrEmpty(albumId) == true)
            {
                albumId = photoAlbum.CreateAlbum(saf.NewAlbumName);
            }

            m_applicationContext.ProcessProgress.Running = false;

            m_progressValue = 0;
            m_applicationContext.ProcessProgress.Maximum = totalSize;
            m_applicationContext.ProcessProgress.IsInfinite = false;
            m_applicationContext.ProcessProgress.Running = true;

            foreach (IImageData imageData in imageFiles)
            {
                string tempFileName = string.Empty;
                if (files.TryGetValue(imageData.FileName, out tempFileName) == true)
                {
                    m_semaphore.WaitOne();
                    m_applicationContext.ProcessProgress.ProcessDescription = this.ToString() + " - " + Path.GetFileName(imageData.FileName);
                    SendOneImage(uploader, imageData, tempFileName, albumId);
                }
            }

            m_applicationContext.ProcessProgress.Running = false;
        }

        private List<string> buildTagList(ReadOnlyCollection<IImageData> imageFiles)
        {
            List<String> tags = new List<string>();
            foreach (IImageData imageData in imageFiles)
            {
                foreach (int tagId in imageData.Tags)
                {
                    IImageTag imageTag = m_applicationContext.ImageTagCollection.GetTag(tagId);
                    if (null != imageTag)
                    {
                        String tagName = imageTag.Name.Replace("\"", String.Empty);
                        if (false == tags.Contains(tagName))
                        {
                            tags.Add(tagName);
                        }
                    }
                }
            }

            return tags;
        }

        void SendOneImage(ImageUploader uploader, IImageData imageData, string fileName, String albumId)
        {
            try
            {
                string description = imageData.Comment;
                List<String> tags = new List<string>();

                foreach (int tagId in imageData.Tags)
                {
                    IImageTag imageTag = m_applicationContext.ImageTagCollection.GetTag(tagId);
                    if (null != imageTag)
                    {
                        tags.Add(imageTag.Name);
                    }
                }

                uploader.Upload(fileName, description, tags, albumId);

                File.Delete(fileName);
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }
            finally
            {
                m_semaphore.Release();
            }
        }

        void uploader_ImageUploadEvent(object sender, ProgressEventArgs e)
        {
            m_progressValue += e.Value;
            m_applicationContext.ProcessProgress.Value = m_progressValue;
            Application.DoEvents();
        }

        #endregion

        #region IPlugin Members

        public string Description
        {
            get { return "Facebook plugin"; }
        }

        public bool Load(IApplicationContext applicationContext)
        {
            m_applicationContext = applicationContext;
            FacebookPluginSettings.SettingsManager = m_applicationContext.SettingsManager;
            FacebookPluginSettings settings = FacebookPluginSettings.Default;

            return true;
        }

        public string Name
        {
            get { return "Facebook plugin"; }
        }

        public void Unload()
        {
            
        }

        public override string ToString()
        {
            return "Facebook";
        }

        #endregion
    }
}
